package org.duang.http.util;

import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.duang.config.Config;
import org.duang.kit.Digests;
import org.duang.kit.ToolsKit;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class HttpUtil {

	public final static String UTF8_CHARSET = "utf-8";
	public final static String ISO88591_CHARSET = "iso-8859-1";
	private static Logger logger = LoggerFactory.getLogger(HttpUtil.class);

	public static void converHeaderCharsetToIso88591(Map<String, String> headers) {
		converHeaderCharset(headers, UTF8_CHARSET, ISO88591_CHARSET);
	}

	public static void convertHeaderCharsetFromIso88591(Map<String, String> headers) {
		converHeaderCharset(headers, ISO88591_CHARSET, UTF8_CHARSET);
	}

	private static void converHeaderCharset(Map<String, String> headers, String formCharset, String toCharset) {
		assert(headers != null);
		try {
			for (Iterator<Entry<String, String>> it = headers.entrySet().iterator(); it.hasNext();) {
				Entry<String, String> entry = it.next();
				if (ToolsKit.isEmpty(entry.getValue()))
					continue;
				entry.setValue(new String(entry.getValue().getBytes(formCharset), toCharset));
			}
		} catch (UnsupportedEncodingException ue) {
			ue.printStackTrace();
		}
	}

	public static String paramToQueryString(Map<String, Object> params) throws UnsupportedEncodingException {
		if (ToolsKit.isEmpty(params))
			return null;
		List<String> list = new ArrayList<String>();
		for (Iterator<Entry<String, Object>> it = params.entrySet().iterator(); it.hasNext();) {
			Entry<String, Object> entry = it.next();
			Object value = entry.getValue();
			if (ToolsKit.isNotEmpty(value)) {
				if (value instanceof java.io.File)
					continue;
				list.add(entry.getKey() + "=" + HttpUtil.urlEncode( value.toString() ) + "&");
			}
		}
		int size = list.size();
		String[] arrayToSort = list.toArray(new String[size]);
		Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
		StringBuilder sb = new StringBuilder();
		for (String value : arrayToSort) {
			sb.append(value);
		}
		if (sb.length() > 0) {
			sb.deleteCharAt(sb.length() - 1);
		}
		return sb.toString();
	}

	private static String urlEncode(String value) throws UnsupportedEncodingException {
		return ToolsKit.isNotEmpty(value)
				? URLEncoder.encode(value, UTF8_CHARSET).replace("+", "%20").replace("*", "%2A").replace("%7E", "~")
				: "";
	}

	public static URI getHttpURI(String url) {
		if (ToolsKit.isEmpty(url)) {
			throw new NullPointerException("url is null");
		}
		try {
			if (!url.startsWith("http://") && !url.startsWith("https://")) {
				throw new IllegalArgumentException("仅支持http或https协议,url必须以http或https开头");
			}
			if (url.endsWith("/")) {
				url = url.substring(0, url.length() - 1);
			}
			if (url.length() < "http://".length()) {
				throw new IllegalArgumentException("url地址无效");
			}
			return new URI(url);
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException(e);
		}
	}

	/**
	 * 将url的请求参数字符串转换为map
	 * 
	 * @param paramStr
	 *            name=老唐&account=laotang
	 * @return Map<String, String>
	 */
	public static Map<String, Object> parseUrlParam2Map(String paramStr) {
		if (ToolsKit.isEmpty(paramStr))
			throw new NullPointerException("params String is null");
		Map<String, Object> map = new HashMap<String, Object>();
		if (paramStr.startsWith("?"))
			paramStr = paramStr.substring(1, paramStr.length());
		String[] arrays = paramStr.split("&");
		try {
			for (String obj : arrays) {
				String[] params = obj.split("=");
				if (params.length == 2) {
					map.put(params[0], java.net.URLDecoder.decode(params[1], UTF8_CHARSET));
				}
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return map;
	}

	public static String createUserAgent() {
		StringBuilder userAgentStr = new StringBuilder();
		userAgentStr.append("duang/2.0.0(").append(System.getProperty("os.name")).append("/")
				.append(System.getProperty("os.version")).append("/").append(System.getProperty("os.arch")).append("/")
				.append(System.getProperty("java.version")).append(")");
		return userAgentStr.toString();
	}

	public static String createAuthorizAtionSignKey() {
		String[] uuidArray = java.util.UUID.randomUUID().toString().toLowerCase().split("-");
		int index = (int) (Math.ceil(Math.random() * 5) - 1);
		StringBuilder result = new StringBuilder();
		for (int i = 0; i < uuidArray.length; i++) {
			if (i != index) {
				result.append(uuidArray[i]).append("-");
			}
		}
		try {
			result.append(Config.getSignKey());
		} catch (Exception e) {
			result.append("duangduangduang");
		}
		try {
			String md5 = Digests.md5toString(ToolsKit.string2InputStream(result.toString(), UTF8_CHARSET));
			uuidArray[index] = md5.substring(md5.length() - 12, md5.length());
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
		result = result.delete(0, result.length());
		for (String tmp : uuidArray) {
			result.append(tmp).append("-");
		}
		if (result.length() > 0) {
			result = result.deleteCharAt(result.length() - 1);
		}
		result.append(index);
		return result.toString();

	}

	public static boolean isDuangAuthorizAtionSignKey(String signKey) {
		boolean isSuccess = false;
		if (ToolsKit.isEmpty(signKey)) {
			logger.warn("API返回的数据签名数据不存在，有可能被第三方篡改!!!");
			return false;
		}
		try {
			int index = Integer.parseInt(Character.toString(signKey.charAt(signKey.length() - 1)));
			signKey = signKey.substring(0, signKey.length() - 1);
			String[] signKeyArray = signKey.split("-");
			String sign = signKeyArray[index];
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < signKeyArray.length; i++) {
				if (i != index) {
					sb.append(signKeyArray[i]).append("-");
				}
			}
			if (sb.length() > 0) {
				try {
					sb.append(Config.getSignKey());
				} catch (Exception e) {
					sb.append("duangdunagduang");
				}
			}
			String md5 = Digests.md5toString(ToolsKit.string2InputStream(sb.toString(), UTF8_CHARSET));
			isSuccess =  sign.equals(md5.substring(md5.length() - 12, md5.length()));
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		if(isSuccess) {
			logger.warn("恭喜，API返回的数据签名验证通过!!!");
		} else {
			logger.warn("API返回的数据签名验证不通过，有可能被第三方篡改!!!");
		}
		return isSuccess;
	}
	
	
	public static boolean isDuangUserAgentSignKey(String userAgent) {
		if(ToolsKit.isEmpty(userAgent)) return false;
		int indexOf = userAgent.lastIndexOf("/");
		String signKeyByResponse = userAgent.substring(indexOf + 1, userAgent.length());
		if (ToolsKit.isEmpty(signKeyByResponse)) {
			logger.warn("API返回的数据签名数据不存在，有可能被第三方篡改!!!");
			return false;
		}
		userAgent = userAgent.substring(0, indexOf) + "&duangkey=" + Config.getSignKey();
		InputStream is = ToolsKit.string2InputStream(userAgent, Config.getEncoding());
		try {
			String tmpSignKey = Digests.md5toString(is);
			if (!signKeyByResponse.equals(tmpSignKey)) {
				logger.warn("API返回的数据签名验证不通过，有可能被第三方篡改!!!");
				return false;
			}
			logger.warn("恭喜，API返回的数据签名验证通过!!!");
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}
}
